﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NCRGEA.AAL;

using System.Data.SqlClient;
using System.Media;
using System.IO;

namespace NCRGEA.Payments
{
    public partial class frmBarcodeEntry : Form
    {
        #region Global Variables

        /// <summary>
        /// This is the number of days that the renewal date can be with and the user can make a payment
        /// </summary>
        const double renewalRange = -30;
        const int cBatchMax = 25;

        const int due = 1;
        const int cashPayMethod = 2;

        int batchID = 0;

        #endregion

        User currentUser = null;
        DataTable myData = new DataTable();
        DataTable gridPayments = new DataTable();

        public frmBarcodeEntry()
        {
            Logger.Log("Barcode cash entry loaded");
            InitializeComponent();
            loadData();

            myData.Columns.Add("MemberID");
            myData.Columns.Add("FirstName");
            myData.Columns.Add("LastName");
            myData.Columns.Add("Amount");
        }

        #region Data Manipulation
        
        private void loadData()
        {
            string query = @"SELECT
                                MAX(p.BatchID) as hBatch
                            FROM
                                payments p";

            DataTable temp = DAL.ExecuteQuery(query);

            query = @"SELECT Amount FROM memDues WHERE Description='Annual Dues'";

            DataTable amountDTable = DAL.ExecuteQuery(query);

            cboxAmount.DataSource = amountDTable;
            cboxAmount.DisplayMember = "Amount";
            cboxAmount.ValueMember = "Amount";

            if (temp != null && temp.Rows.Count == 1 && temp.Rows[0][0] != DBNull.Value)
                batchID = (int)temp.Rows[0][0];
            else
                batchID = 0;

            batchID++;

            lblBatchID.Text = "Current BatchID: " + batchID;

            lblBatchID.Visible = true;
        }

        #endregion

        #region Control Manipulation

        /// <summary>
        /// Clears the memberID textbox for the next scan
        /// </summary>
        private void nextEntry()
        {
            txtMemID.Text = string.Empty;
            txtMemID.Focus();
        }

        private bool ValidateInput()
        {
            double cash;

            if (cboxAmount.SelectedIndex <= -1)
            {
                MessageBox.Show("Please select a monatary value.");
                return false;
            }

            if (txtMemID.Text == string.Empty)
            {
                MessageBox.Show("Please enter a memberID.", "No MemberID Entered");
                return false;
            }


            string test = ((DataTable)cboxAmount.DataSource).Rows[cboxAmount.SelectedIndex]["Amount"].ToString();

            if (double.TryParse(test, out cash))
                return true;
            
            //MessageBox.Show("Please select a valid money amount.");
            return false;
        }

        private void AddPaymentToGrid(int MemberID, string fName, string lName, double amount)
        {
            myData.Rows.Add(MemberID, fName, lName, amount);
            gcCurrentBatch.DataSource = myData;
        }

        /// <summary>
        /// Check to make sure that the member can actually make a payment
        /// </summary>
        /// <returns>Returns true if the member can make a payment, false if the cannot</returns>
        private bool MakePayment()
        {
            string query = @"SELECT
                                MemberID,
                                FirstName,
                                LastName,
                                RenewalDate,
                                Name
                             FROM
                                memInfo mi
                                    INNER JOIN
                                        memTypes mt
                                    ON
                                        mi.TypeID = mt.TypeID
                             WHERE
                                mi.MemberID = @memberID";

            SqlParameter[] param = new SqlParameter[1];
            
            if (string.IsNullOrWhiteSpace(txtMemID.Text))
                return false;
            
            int memberID = -1;

            if (!int.TryParse(txtMemID.Text, out memberID) || memberID == -1)
                return false;

            //Check to see if this member is already in the payments list
            foreach (DataRow dr in myData.Rows)
                if (int.Parse(dr["MemberID"].ToString()) == memberID)
                {
                    MessageBox.Show("This member has already made a payment!");
                    txtMemID.Text = string.Empty;
                    return false;
                }

            param[0] = new SqlParameter("@memberID", int.Parse(txtMemID.Text));

            int memID = 0;
            
            Logger.Log("MemberID : " + int.Parse(txtMemID.Text));
            Logger.Log("Query: " + query);

            DataTable ldMemberPaymentInfo = DAL.ExecuteQuery(query,param);

            Logger.Log("Member Info table loaded.");

            if (ldMemberPaymentInfo == null || ldMemberPaymentInfo.Rows.Count == 0)
            {
                return false;
            }
            DataRow row = ldMemberPaymentInfo.Rows[0];


            double amount = double.Parse((((DataTable)cboxAmount.DataSource).Rows[cboxAmount.SelectedIndex]["Amount"].ToString()));

            int memberid = (int)row["MemberID"];
            string fName = row["FirstName"].ToString();
            string lName = row["LastName"].ToString();
            string typeName = row["Name"].ToString();

            if (doRenew(row, typeName))
            {
                Logger.Log("Processing payment. Method: checkMember().");

                memID = (int)row["MemberID"];

                DateTime nTime = DateTime.Today;

                int staffID = ((frmMain)(this.MdiParent)).CurrentUser.StaffID;

                try
                {
                    if (UAL.SavePayment(memberid, cashPayMethod, null, amount, nTime, staffID, due))
                    {
                        updateRenewalDate(row);
                        changeStatus(memID);
                        AddPaymentToGrid(memberid, fName, lName, amount);
                    }
                }
                catch (Exception e)
                {
                    Logger.Log("Error occured while attempting to save a payment. Method: checkMember().: " + e.Message);
                }
            }

            return true;
        }

        /// <summary>
        /// Determines whether the member's status is free or lifetime. If not, set it to active.
        /// </summary>
        /// <param name="memID"></param>
        private void changeStatus(int memID)
        {
            string query = @"SELECT
                                *
                             FROM
                                memInfo mi
                             WHERE
                                mi.TypeID <> 3 AND mi.TypeID <> 4 AND mi.MemberID = "+ memID;

            DataTable temp = DAL.ExecuteQuery(query);
            
            Logger.Log("Determining whether this member is free or lifetime.");

            if (temp == null || temp.Rows.Count == 0)
                return;

            foreach (DataRow row in temp.Rows)
            {
                query = @"UPDATE
                            memInfo
                          SET
                            TypeID = 1
                          WHERE
                            MemberID = " + memID;

                DAL.ExecuteNonQuery(query);

                Logger.Log("Member:" + memID + " TypeID has been set to 1(Active)");

                query = @"SELECT
                            *
                          FROM
                            payments
                          WHERE
                            MemberID = @memberID";

                SqlParameter[] param = new SqlParameter[1];

                param[0] = new SqlParameter("@memberID", memID);

                temp = DAL.ExecuteQuery(query,param);

                Logger.Log("Member detected within Payments");

                if (temp == null || temp.Rows.Count == 0)
                    return;
                
                //Update batchIDs
                query = @"UPDATE
                            payments
                         SET
                            BatchID = @batchID
                        WHERE
                            MemberID = @memberID AND CAST(Date AS DATE) = CAST(GETDATE() AS DATE)";
                SqlParameter[] param2 = new SqlParameter[2];

                param2[0] = new SqlParameter("@batchID", batchID);
                param2[1] = new SqlParameter("@memberID", memID);

                DAL.ExecuteNonQuery(query, param2);

                Logger.Log("Batch ID has been made");
            }
        }

        /// <summary>
        /// Updates the renewal date of the member by one year, either from today or one year from their renewal
        /// date.
        /// </summary>
        /// <param name="row"></param>
        private void updateRenewalDate(DataRow row)
        {
            string nTime = row["RenewalDate"].ToString();
            string memberType = row[""].ToString();
            DateTime temp;

            if (nTime == string.Empty)
            {
                temp = DateTime.Today;
                temp = temp.AddYears(1);
            }
            else
            {
                temp = DateTime.Parse(nTime);
                temp = temp.AddYears(1);
            }
            
            nTime = temp.Year + "/" + temp.Month + "/" + temp.Day;

            Logger.Log("Calculated Renewal Date: " + nTime);

            string query = @"UPDATE
                                memInfo
                            SET
                                RenewalDate = @RenewalDate
                            WHERE
                                MemberID = @MemberID";

            SqlParameter[] param = new SqlParameter[2];

            param[0] = new SqlParameter("@RenewalDate", nTime);
            param[1] = new SqlParameter("@MemberID", (int)row["MemberID"]);

            DAL.ExecuteNonQuery(query, param);

            Logger.Log("Updated renewal date for: " + row["FirstName"].ToString() + " " + row["LastName"].ToString());
        }

        /// <summary>
        /// Used to determine whether the member can renew or no
        /// </summary>
        /// <returns>Returns true if the member can, false if they cannot.</returns>
        private bool doRenew(DataRow row, string sTemp)
        {
            string path;
            path = System.IO.Path.GetDirectoryName(
               System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);

            path += "\\Resources\\Computer Error.wav-17394-Free-Loops.com.mp3";

            SoundPlayer simpleSound = new SoundPlayer(path);
            

            if (sTemp == "LifeTime" || sTemp == "Deceased" || sTemp == "Removed" || sTemp == "Free")
            {
                /*
                try
                {
                    simpleSound.Play();
                }
                catch (FileNotFoundException e)
                {
                    Logger.Log("Error while playing sound file. " + e.Message);
                }*/

                MessageBox.Show("This member is unable to make payments.", "Member Payment Error");
                return false;
            }

            Logger.Log("Member is active. Still pending date");
            
            DateTime tTemp = DateTime.MinValue;
            TimeSpan range = new TimeSpan();

            if (row["RenewalDate"].ToString() == string.Empty)
            {
                tTemp = DateTime.MinValue;
                range = DateTime.Today - tTemp;
            }
            else
            {
                tTemp = (DateTime)row["RenewalDate"];
                range = DateTime.Today - tTemp;
            }

            if (range.TotalDays < renewalRange)
            {
                Logger.Log("Comparing date, is not time for member to renew");
                
                /*
                try
                {
                    simpleSound.Play();
                }
                catch (FileNotFoundException e)
                {
                    Logger.Log("Error while playing sound file. " + e.Message);
                }*/

                MessageBox.Show("This member's renewal period is not up yet.", "Renewal Too Soon");

                return false;
            }

            Logger.Log("Member can be renewed. Method doRenew().");

            return true;
        }


        /// <summary>
        /// This method determines whether there are 25 members in this batch already
        /// </summary>
        /// <returns>True if there are 25 payments in this batch, false otherwise</returns>
        private bool batchMax()
        {
            string query = @"SELECT
                                COUNT(BatchID) as bCount
                            FROM
                                payments p
                            WHERE
                                BatchID =" + batchID;

            DataTable temp = DAL.ExecuteQuery(query);

            int bNum = -1;

            if (temp.Rows[0]["bCount"].ToString() == string.Empty)
                return false;
            else
                bNum = (int)temp.Rows[0]["bCount"];

            if (bNum + 1 > cBatchMax)
            {
                return true;
            }

            return false;
        }

        #endregion

        private void btnSubmit_Click(object sender, EventArgs e)
        {
            PerformEntry();
        }

        private void PerformEntry()
        {
            if (ValidateInput())
            {
                Logger.Log("Starting Query.");
                if (MakePayment())
                {
                    Logger.Log("Payment processed.");
                    nextEntry();
                }
            }
            else
            {
                Logger.Log("Invalid index selected.");
            }
        }

        private void btnCloseBatch_Click(object sender, EventArgs e)
        {
            batchID = batchID + 1;

            gcCurrentBatch.DataSource = null;

            myData.Clear();

            lblBatchID.Text = "Current BatchID: " + batchID;
        }

        private void txtMemID_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ((Keys)e.KeyChar == Keys.Enter)
            {
                PerformEntry();
            }
        }
    }
}
